package com.cy.ppj.comm.interceptor;

import com.aliyun.oss.OSSClient;
import com.cy.ppj.comm.annotation.OssUrl;
import com.cy.ppj.comm.constant.Constants;
import com.cy.ppj.comm.utils.CommonUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.cache.CacheKey;
import org.apache.ibatis.executor.Executor;
import org.apache.ibatis.mapping.BoundSql;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.plugin.*;
import org.apache.ibatis.session.ResultHandler;
import org.apache.ibatis.session.RowBounds;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.lang.reflect.Field;
import java.net.URL;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.Properties;
import java.util.stream.Stream;

/**
 * @description: OSS路径拦截器
 * @author: Ocean
 * @create: 2018-08-07 19:31
 **/
@Slf4j
@Component
@Intercepts({
        @Signature(type = Executor.class, method = "query", args = {MappedStatement.class, Object.class, RowBounds.class,
                ResultHandler.class, CacheKey.class, BoundSql.class})
})
public class OssUrlInterceptor implements Interceptor {

    @Autowired
    private OSSClient ossClient;

    @Override
    public Object intercept(Invocation invocation) throws Throwable {

        Object result = invocation.proceed();
        if (result instanceof List) {
            List list = (List) result;

            if (list.stream().noneMatch(obj -> obj.getClass().isAnnotationPresent(OssUrl.class))) {
                //没有包含注解直接返回
                return result;
            }

            //Oss客户端
            Date expiration = CommonUtils.addTime(2, Calendar.HOUR_OF_DAY);

            list.stream().filter(obj -> obj.getClass().isAnnotationPresent(OssUrl.class)).forEach(obj -> {
                // 获取实体类的所有属性，返回Field数组
                Field[] field = obj.getClass().getDeclaredFields();
                Stream.of(field).filter(f -> f.isAnnotationPresent(OssUrl.class))
                        .filter(f -> String.class.equals(f.getType()))
                        .forEach(f -> {
                            //设置些属性是可以访问的
                            f.setAccessible(true);
                            try {
                                //得到此属性的值
                                Object value = f.get(obj);
                                String key = String.valueOf(value);
                                URL url = ossClient.generatePresignedUrl(Constants.FILE_PTAH, key, expiration);
                                f.set(obj, url.toString());
                            } catch (IllegalAccessException e) {
                                log.error("OssUrlInterceptor intercept error:", e);
                            }
                        });
            });
        }

        return result;
    }

    @Override
    public Object plugin(Object target) {
        return Plugin.wrap(target, this);
    }

    @Override
    public void setProperties(Properties properties) {
    }
}
